package com.kanq.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.kanq.memory.RedisChatMemoryRepository;
import com.kanq.pojo.entity.SensitiveWord;
import com.kanq.service.SensitiveWordService;
import io.micrometer.observation.ObservationRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.DefaultChatClientBuilder;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SafeGuardAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.ChatMemoryRepository;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.document.MetadataMode;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.openai.OpenAiEmbeddingModel;
import org.springframework.ai.openai.OpenAiEmbeddingOptions;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.stream.Collectors;

@Slf4j
@Configuration
public class MultipleModelsConfig {

    private final SensitiveWordService sensitiveWordService;

    private final ToolCallbackProvider toolCallbackProvider;
    @Value("${spring.ai.openai.chat.options.model}")
    String modelName;
    @Value("${spring.ai.openai.base-url}")
    String url;
    @Value("${spring.ai.openai.api-key}")
    String sk;
    @Value("${spring.ai.openai.embedding.options.model}")
    String embeddingModelName;

    public MultipleModelsConfig(SensitiveWordService sensitiveWordService, ToolCallbackProvider toolCallbackProvider) {
        this.sensitiveWordService = sensitiveWordService;
        this.toolCallbackProvider = toolCallbackProvider;
    }

    @Bean
    public ChatMemoryRepository chatMemoryRepository(StringRedisTemplate stringRedisTemplate) {
        // 默认情况下，如果尚未配置其他存储库，则 Spring AI 会自动配置ChatMemoryRepository类型的 beanInMemoryChatMemoryRepository可以直接在应用程序中使用。
        // 这里手动创建内存聊天记忆存储库
        return new RedisChatMemoryRepository(stringRedisTemplate, new ObjectMapper());
    }

    @Bean
    public ChatMemory chatMemory(ChatMemoryRepository chatMemoryRepository) {
        // 注册聊天上下文记忆机制
        return MessageWindowChatMemory
                .builder()
                .chatMemoryRepository(chatMemoryRepository)
                .maxMessages(20)   // 聊天记忆条数
                .build();
    }

    @Bean(name = "defaultChat")
    public ChatClient defaultChatClient(OpenAiChatModel openAiChatModel, ChatMemory chatMemory) {
        DefaultChatClientBuilder defaultChatClientBuilder = new DefaultChatClientBuilder(openAiChatModel, ObservationRegistry.NOOP, null);
        return defaultChatClientBuilder
                .defaultSystem("您好！我是您的智能问答助手冲冲同学。我可以帮助您使用mcp工具完成以下任务：\n1. 顺序思考(sequential-thinking)\n2. 内存操作(memory)\n3. MySQL数据库操作(mysql)\n4. MCP工具集成")

                .defaultOptions(OpenAiChatOptions.builder()
                        .model(modelName)
                        .build())
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build(),
                        SafeGuardAdvisor.builder()
                                .sensitiveWords(sensitiveWordService.list().stream().map(SensitiveWord::getWord).collect(Collectors.toList())) // 从数据库读取敏感词
                                .order(2) // 设置优先级
                                .failureResponse("抱歉，我无法回答这个问题。").build(), // 敏感词过滤失败时的响应
                        new SimpleLoggerAdvisor())
                .defaultToolCallbacks(toolCallbackProvider) // 添加MCP工具集成
                .build();


//        return ChatClient.builder(openAiChatModel)
//                .defaultSystem("您好！我是您的智能问答助手冲冲同学。我可以帮助您使用mcp工具完成以下任务：\n1. 顺序思考(sequential-thinking)\n2. 内存操作(memory)\n3. MySQL数据库操作(mysql)")
//                .defaultToolCallbacks(tools)
//                .defaultAdvisors(
//                        //内存存储对话记忆
//                        MessageChatMemoryAdvisor.builder(chatMemory).build(),
////                        new PromptChatMemoryAdvisor(inMemoryChatMemory()),
//                        // QuestionAnswerAdvisor 此顾问使用矢量存储提供问答功能，实现RAG（检索增强生成）模式
////                        QuestionAnswerAdvisor.builder(vectorStore).order(1).build(),
//                        // SafeGuardAdvisor是一个安全防护顾问，它确保生成的内容符合道德和法律标准。
//                        SafeGuardAdvisor.builder().sensitiveWords(List.of("色情", "暴力")) // 敏感词列表
//                                .order(2) // 设置优先级
//                                .failureResponse("抱歉，我无法回答这个问题。").build(), // 敏感词过滤失败时的响应
////                        new ReReadingAdvisor(),
//                        // SimpleLoggerAdvisor是一个记录ChatClient的请求和响应数据的顾问。这对于调试和监控您的AI交互非常有用，建议将其添加到链的末尾。
//                        new SimpleLoggerAdvisor())
//                .build();
    }

    @Primary
    @Bean(name = "defaultEmbedding")
    public EmbeddingModel embeddingChatClient() {
        return new OpenAiEmbeddingModel(OpenAiApi.builder().apiKey(sk).baseUrl(url).build(), MetadataMode.EMBED, OpenAiEmbeddingOptions.builder().model(embeddingModelName).build());
    }
}
